/*
    作者：zx
    时间：2022.11.11
    描述：日志输出功能的实现
*/

#include "tools/log.h"
#include "comm/cpu_instr.h"
#include <stdarg.h>
#include "tools/klib.h"
#include "cpu/irq.h"
#include "ipc/mutex.h"
#include "dev/console.h"
#include "dev/dev.h"

// 串行接口端口
#define COM1_PORT 0x3F8
// 串行接口开关
#define LOG_USE_SWITCH 0

static mutex_t mutex;
// 对哪个设备进行printf
static int log_dev_id;

void log_init(void)
{   
    mutex_init(&mutex);
    log_dev_id = dev_open(DEV_TTY, 0, 0);

#if LOG_USE_SWITCH
    // 代码不需要深究 暂时使用串行接口进行日志输出
    // 之后会改
    // 关闭串行接口中断
    outb(COM1_PORT+1,0x00);
    // 串行接口传输速度
    outb(COM1_PORT+3,0x80);
    outb(COM1_PORT+0,0x03);
    outb(COM1_PORT+1,0x00);
    outb(COM1_PORT+3,0x03);
    outb(COM1_PORT+2,0xc7);
    outb(COM1_PORT+4,0x0F); 
#endif // LOG_USE_SWITCH
}

void log_printf(const char * fmt, ...)
{
    // stdargs.h 文件 取不定长参数
    va_list args;
    va_start(args,fmt);

    // 格式化后的字符串
    char buff[128];
    kernel_memset(buff, '\0', sizeof(buff));

    kernel_vsprintf(buff,fmt,args);
    // 释放资源
    va_end(args);  

    mutex_lock(&mutex);

#if LOG_USE_SWITCH
    const char * s = buff;
    while (*s!='\0')
    {
        while( (inb(COM1_PORT+5)&(1<<6)) == 0 );
        outb(COM1_PORT, *s++);
    }
    // qemu模拟器 自己的设定
    // 换行
    outb(COM1_PORT, '\r');
    // 回车
    outb(COM1_PORT, '\n');
#else 
    // console_write(0, buff, kernel_strlen(buff));
    dev_write(log_dev_id, 0, buff, kernel_strlen(buff));
    char ch = '\n';
    // console_write(0, &ch, 1);
    dev_write(log_dev_id, 0, &ch, 1);
#endif // LOG_USE_SWITCH
    mutex_unlock(&mutex);
}